﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Web.Mvc;
using System.Web.Routing;
using Ams.Extensions;

namespace Ams.Mvc.Bootstrap
{
    public enum Form
    {
        [Description("form")]
        Normal,
        
        [Description("form-horizontal")]
        Horizontal,
        
        [Description("form-inline")]
        Inline
    }

    public static class BootstrapFormExtensions
    {
        internal static string DefaultLabelClasses = "col-md-2 col-sm-7";
        internal static string DefaultEditorClasses = "col-lg-7 col-md-9";
        internal static string DefaultValidationClasses = "col-lg-3 col-lg-offset-0 col-md-7 col-md-offset-2";

        #region Form
        public static BootstrapMvcForm Form(this BootstrapHelper helper)
        {
            var actionName = helper.ViewContext.RouteData.GetRequiredString("action");
            var controllerName = helper.ViewContext.RouteData.GetRequiredString("controller");
            return Form(helper, actionName, controllerName, null, FormMethod.Post, HtmlHelper.AnonymousObjectToHtmlAttributes(null));
        }
        public static BootstrapMvcForm Form(this BootstrapHelper helper, object htmlAttributes)
        {
            var actionName = helper.ViewContext.RouteData.GetRequiredString("action");
            var controllerName = helper.ViewContext.RouteData.GetRequiredString("controller");
            return Form(helper, actionName, controllerName, null, FormMethod.Post, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
        }
        public static BootstrapMvcForm Form(this BootstrapHelper helper, RouteValueDictionary routeValues)
        {
            var actionName = helper.ViewContext.RouteData.GetRequiredString("action");
            var controllerName = helper.ViewContext.RouteData.GetRequiredString("controller");
            return Form(helper, actionName, controllerName, routeValues, FormMethod.Post, HtmlHelper.AnonymousObjectToHtmlAttributes(null));
        }
        public static BootstrapMvcForm Form(this BootstrapHelper helper, string actionName, string controllerName)
        {
            return Form(helper, actionName, controllerName, null, FormMethod.Post, HtmlHelper.AnonymousObjectToHtmlAttributes(null));
        }
        public static BootstrapMvcForm Form(this BootstrapHelper helper, string actionName, FormMethod method)
        {
            var currentController = helper.ViewContext.RouteData.GetRequiredString("controller");
            return Form(helper, actionName, currentController, null, FormMethod.Post, HtmlHelper.AnonymousObjectToHtmlAttributes(null));
        }
        public static BootstrapMvcForm Form(this BootstrapHelper helper, string actionName, string controllerName, object routeValues)
        {
            return Form(helper, actionName, controllerName, routeValues, FormMethod.Post, HtmlHelper.AnonymousObjectToHtmlAttributes(null));
        }
        public static BootstrapMvcForm Form(this BootstrapHelper helper, string actionName, string controllerName, RouteValueDictionary routeValues)
        {
            return Form(helper, actionName, controllerName, routeValues, FormMethod.Post, HtmlHelper.AnonymousObjectToHtmlAttributes(null));
        }
        public static BootstrapMvcForm Form(this BootstrapHelper helper, string actionName, string controllerName, FormMethod method)
        {
            return Form(helper, actionName, controllerName, null, method, HtmlHelper.AnonymousObjectToHtmlAttributes(null));
        }
        public static BootstrapMvcForm Form(this BootstrapHelper helper, string actionName, string controllerName, object routeValues, FormMethod method)
        {
            return Form(helper, actionName, controllerName, routeValues, method, HtmlHelper.AnonymousObjectToHtmlAttributes(null));
        }
        public static BootstrapMvcForm Form(this BootstrapHelper helper, string actionName, string controllerName, RouteValueDictionary routeValues, FormMethod method)
        {
            return Form(helper, actionName, controllerName, routeValues, method, HtmlHelper.AnonymousObjectToHtmlAttributes(null));
        }
        public static BootstrapMvcForm Form(this BootstrapHelper helper, string actionName, string controllerName, FormMethod method, object htmlAttributes)
        {
            return Form(helper, actionName, controllerName, null, method, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
        }
        public static BootstrapMvcForm Form(this BootstrapHelper helper, string actionName, string controllerName, FormMethod method, IDictionary<string, object> htmlAttributes)
        {
            return Form(helper, actionName, controllerName, null, method, htmlAttributes);
        }
        public static BootstrapMvcForm Form(this BootstrapHelper helper, string actionName, string controllerName, object routeValues, FormMethod method, object htmlAttributes)
        {
            return Form(helper, actionName, controllerName, routeValues, method, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
        }
        public static BootstrapMvcForm Form(this BootstrapHelper helper, string actionName, string controllerName, RouteValueDictionary routeValues, FormMethod method, IDictionary<string, object> htmlAttributes)
        {
            return Form(helper, actionName, controllerName, routeValues, method, htmlAttributes, Bootstrap.Form.Normal);
        } 
        #endregion

        #region HorizontalForm
        public static BootstrapMvcForm HorizontalForm(this BootstrapHelper helper)
        {
            var actionName = helper.ViewContext.RouteData.GetRequiredString("action");
            var controllerName = helper.ViewContext.RouteData.GetRequiredString("controller");
            return HorizontalForm(helper, actionName, controllerName, null, FormMethod.Post, HtmlHelper.AnonymousObjectToHtmlAttributes(null));
        }
        public static BootstrapMvcForm HorizontalForm(this BootstrapHelper helper, object htmlAttributes)
        {
            var actionName = helper.ViewContext.RouteData.GetRequiredString("action");
            var controllerName = helper.ViewContext.RouteData.GetRequiredString("controller");
            return HorizontalForm(helper, actionName, controllerName, helper.ViewContext.RouteData.Values, FormMethod.Post, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
        }
        public static BootstrapMvcForm HorizontalForm(this BootstrapHelper helper, RouteValueDictionary routeValues)
        {
            var actionName = helper.ViewContext.RouteData.GetRequiredString("action");
            var controllerName = helper.ViewContext.RouteData.GetRequiredString("controller");
            return HorizontalForm(helper, actionName, controllerName, routeValues, FormMethod.Post, HtmlHelper.AnonymousObjectToHtmlAttributes(null));
        }
        public static BootstrapMvcForm HorizontalForm(this BootstrapHelper helper, string actionName, string controllerName)
        {
            return HorizontalForm(helper, actionName, controllerName, null, FormMethod.Post, HtmlHelper.AnonymousObjectToHtmlAttributes(null));
        }
        public static BootstrapMvcForm HorizontalForm(this BootstrapHelper helper, string actionName, FormMethod method)
        {
            var currentController = helper.ViewContext.RouteData.GetRequiredString("controller");
            return HorizontalForm(helper, actionName, currentController, null, FormMethod.Post, HtmlHelper.AnonymousObjectToHtmlAttributes(null));
        }
        public static BootstrapMvcForm HorizontalForm(this BootstrapHelper helper, string actionName, string controllerName, object routeValues)
        {
            return HorizontalForm(helper, actionName, controllerName, routeValues, FormMethod.Post, HtmlHelper.AnonymousObjectToHtmlAttributes(null));
        }
        public static BootstrapMvcForm HorizontalForm(this BootstrapHelper helper, string actionName, string controllerName, RouteValueDictionary routeValues)
        {
            return HorizontalForm(helper, actionName, controllerName, routeValues, FormMethod.Post, HtmlHelper.AnonymousObjectToHtmlAttributes(null));
        }
        public static BootstrapMvcForm HorizontalForm(this BootstrapHelper helper, string actionName, string controllerName, FormMethod method)
        {
            return HorizontalForm(helper, actionName, controllerName, null, method, HtmlHelper.AnonymousObjectToHtmlAttributes(null));
        }
        public static BootstrapMvcForm HorizontalForm(this BootstrapHelper helper, string actionName, string controllerName, object routeValues, FormMethod method)
        {
            return HorizontalForm(helper, actionName, controllerName, routeValues, method, HtmlHelper.AnonymousObjectToHtmlAttributes(null));
        }
        public static BootstrapMvcForm HorizontalForm(this BootstrapHelper helper, string actionName, string controllerName, RouteValueDictionary routeValues, FormMethod method)
        {
            return HorizontalForm(helper, actionName, controllerName, routeValues, method, HtmlHelper.AnonymousObjectToHtmlAttributes(null));
        }
        public static BootstrapMvcForm HorizontalForm(this BootstrapHelper helper, string actionName, string controllerName, FormMethod method, object htmlAttributes)
        {
            return HorizontalForm(helper, actionName, controllerName, null, method, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
        }
        public static BootstrapMvcForm HorizontalForm(this BootstrapHelper helper, string actionName, string controllerName, FormMethod method, IDictionary<string, object> htmlAttributes)
        {
            return HorizontalForm(helper, actionName, controllerName, null, method, htmlAttributes);
        }
        public static BootstrapMvcForm HorizontalForm(this BootstrapHelper helper, string actionName, string controllerName, object routeValues, FormMethod method, object htmlAttributes)
        {
            return HorizontalForm(helper, actionName, controllerName, routeValues, method, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
        }
        public static BootstrapMvcForm HorizontalForm(this BootstrapHelper helper, string actionName, string controllerName, RouteValueDictionary routeValues, FormMethod method, IDictionary<string, object> htmlAttributes)
        {
            return Form(helper, actionName, controllerName, routeValues, method, htmlAttributes, Bootstrap.Form.Horizontal);
        } 
        #endregion

        #region InlineForm
        public static BootstrapMvcForm InlineForm(this BootstrapHelper helper)
        {
            var actionName = helper.ViewContext.RouteData.GetRequiredString("action");
            var controllerName = helper.ViewContext.RouteData.GetRequiredString("controller");
            return InlineForm(helper, actionName, controllerName, null, FormMethod.Post, HtmlHelper.AnonymousObjectToHtmlAttributes(null));
        }
        public static BootstrapMvcForm InlineForm(this BootstrapHelper helper, object routeValues)
        {
            var actionName = helper.ViewContext.RouteData.GetRequiredString("action");
            var controllerName = helper.ViewContext.RouteData.GetRequiredString("controller");
            return InlineForm(helper, actionName, controllerName, null, FormMethod.Post, HtmlHelper.AnonymousObjectToHtmlAttributes(null));
        }
        public static BootstrapMvcForm InlineForm(this BootstrapHelper helper, RouteValueDictionary routeValues)
        {
            var actionName = helper.ViewContext.RouteData.GetRequiredString("action");
            var controllerName = helper.ViewContext.RouteData.GetRequiredString("controller");
            return InlineForm(helper, actionName, controllerName, null, FormMethod.Post, HtmlHelper.AnonymousObjectToHtmlAttributes(null));
        }
        public static BootstrapMvcForm InlineForm(this BootstrapHelper helper, string actionName, string controllerName)
        {
            return InlineForm(helper, actionName, controllerName, null, FormMethod.Post, HtmlHelper.AnonymousObjectToHtmlAttributes(null));
        }
        public static BootstrapMvcForm InlineForm(this BootstrapHelper helper, string actionName, FormMethod method)
        {
            var currentController = helper.ViewContext.RouteData.GetRequiredString("controller");
            return InlineForm(helper, actionName, currentController, null, FormMethod.Post, HtmlHelper.AnonymousObjectToHtmlAttributes(null));
        }
        public static BootstrapMvcForm InlineForm(this BootstrapHelper helper, string actionName, string controllerName, object routeValues)
        {
            return InlineForm(helper, actionName, controllerName, routeValues, FormMethod.Post, HtmlHelper.AnonymousObjectToHtmlAttributes(null));
        }
        public static BootstrapMvcForm InlineForm(this BootstrapHelper helper, string actionName, string controllerName, RouteValueDictionary routeValues)
        {
            return InlineForm(helper, actionName, controllerName, routeValues, FormMethod.Post, HtmlHelper.AnonymousObjectToHtmlAttributes(null));
        }
        public static BootstrapMvcForm InlineForm(this BootstrapHelper helper, string actionName, string controllerName, FormMethod method)
        {
            return InlineForm(helper, actionName, controllerName, null, method, HtmlHelper.AnonymousObjectToHtmlAttributes(null));
        }
        public static BootstrapMvcForm InlineForm(this BootstrapHelper helper, string actionName, string controllerName, object routeValues, FormMethod method)
        {
            return InlineForm(helper, actionName, controllerName, routeValues, method, HtmlHelper.AnonymousObjectToHtmlAttributes(null));
        }
        public static BootstrapMvcForm InlineForm(this BootstrapHelper helper, string actionName, string controllerName, RouteValueDictionary routeValues, FormMethod method)
        {
            return InlineForm(helper, actionName, controllerName, routeValues, method, HtmlHelper.AnonymousObjectToHtmlAttributes(null));
        }
        public static BootstrapMvcForm InlineForm(this BootstrapHelper helper, string actionName, string controllerName, FormMethod method, object htmlAttributes)
        {
            return InlineForm(helper, actionName, controllerName, null, method, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
        }
        public static BootstrapMvcForm InlineForm(this BootstrapHelper helper, string actionName, string controllerName, FormMethod method, IDictionary<string, object> htmlAttributes)
        {
            return InlineForm(helper, actionName, controllerName, null, method, htmlAttributes);
        }
        public static BootstrapMvcForm InlineForm(this BootstrapHelper helper, string actionName, string controllerName, object routeValues, FormMethod method, object htmlAttributes)
        {
            return InlineForm(helper, actionName, controllerName, routeValues, method, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
        }
        public static BootstrapMvcForm InlineForm(this BootstrapHelper helper, string actionName, string controllerName, RouteValueDictionary routeValues, FormMethod method, IDictionary<string, object> htmlAttributes)
        {
            return Form(helper, actionName, controllerName, routeValues, method, htmlAttributes, Bootstrap.Form.Inline);
        } 
        #endregion

        #region Main Form Creation Method
        private static BootstrapMvcForm Form(this BootstrapHelper helper, string actionName, string controllerName, RouteValueDictionary routeValues, FormMethod method, IDictionary<string, object> htmlAttributes, Form formType)
        {
            routeValues = routeValues ?? helper.ViewContext.RouteData.Values;

            helper.Html.EnableClientValidation();
            helper.Html.EnableUnobtrusiveJavaScript();
            
            var attibutes = htmlAttributes ?? new Dictionary<string, object>();
            var formClassName = formType.GetDisplayText();

            HtmlMod.AppendToAttributeList(ref  attibutes, "class", formClassName);
            if (!attibutes.ContainsKey("role")) attibutes.Add("role", "form");

            string formAction = UrlHelper.GenerateUrl(null /* routeName */, actionName, controllerName, routeValues, helper.Html.RouteCollection, helper.Html.ViewContext.RequestContext, true /* includeImplicitMvcValues */);

            TagBuilder tagBuilder = new TagBuilder("form");
            tagBuilder.MergeAttributes(attibutes);
            tagBuilder.MergeAttribute("action", formAction);
            tagBuilder.MergeAttribute("method", HtmlHelper.GetFormMethodString(method), true);

            helper.Html.ViewContext.Writer.Write(tagBuilder.ToString(TagRenderMode.StartTag));
            
            var form = new BootstrapMvcForm(helper.Html.ViewContext);
            form.FormType = formType;
            if (String.IsNullOrWhiteSpace(form.LabelClasses)) form.LabelClasses = DefaultLabelClasses;
            if (String.IsNullOrWhiteSpace(form.EditorClasses)) form.EditorClasses = DefaultEditorClasses;
            if (String.IsNullOrWhiteSpace(form.ValidationClasses)) form.ValidationClasses = DefaultValidationClasses;
            
            helper.Form = form;
            return form;
        }
        #endregion
    }
}
